//********************************************************************
//	created:	12:10:2011   15:17
//	filename: 	xmlparser.h
//	author:		tiamo
//	purpose:	xml parser
//********************************************************************

#pragma once

namespace utils
{
	//
	// xml parser
	//
	class XmlParser
	{
	public:
		//
		// constructor
		//
		XmlParser()															{mParserContext = nullptr;}

		//
		// destructor
		//
		~XmlParser()														{reset();}

		//
		// reset
		//
		void reset();

		//
		// parse
		//
		void parse(DataBuffer const& documentContent, bool htmlMode);

		//
		// parse
		//
		void parse(DataBuffer&& documentContent, bool htmlMode);

		//
		// get nodes set
		//
		std::vector<xmlNodePtr> getNodes(wchar_t const* nodesPath, xmlNodePtr startNode = nullptr);

		//
		// get node
		//
		xmlNodePtr getNode(wchar_t const* nodePath, xmlNodePtr startNode = nullptr);

		//
		// get attribute
		//
		UniString getString(wchar_t const* valuePath, xmlNodePtr startNode = nullptr, bool* checkExist = nullptr);

		//
		// get number
		//
		double getDouble(wchar_t const* valuePath, xmlNodePtr startNode = nullptr, bool* checkExist = nullptr);

		//
		// get number
		//
		template<typename RetType>
		RetType getNumber(wchar_t const* valuePath, xmlNodePtr startNode = nullptr, bool* checkExist = nullptr)
		{
			return static_cast<RetType>(getDouble(valuePath, startNode, checkExist));
		}

		//
		// get attribute
		//
		UniString getAttribute(xmlNodePtr xmlNode, wchar_t const* attributeName);

		//
		// get content
		//
		UniString getContent(xmlNodePtr xmlNode);

		//
		// get children count
		//
		uint32_t getChildrenCount(xmlNodePtr xmlNode) const					{return static_cast<uint32_t>(xmlChildElementCount(xmlNode));}

		//
		// get first child
		//
		xmlNodePtr getFirstChild(xmlNodePtr xmlNode) const					{return xmlFirstElementChild(xmlNode);}

		//
		// get next sibling
		//
		xmlNodePtr getNextSibling(xmlNodePtr xmlNode) const					{return xmlNextElementSibling(xmlNode);}

		//
		// get name
		//
		UniString getNodeName(xmlNodePtr xmlNode) const						{return utf8ToWide(static_cast<char const*>(static_cast<void const*>(xmlNode->name)));}

	private:
		//
		// parse xml
		//
		void parseXml();

		//
		// parse html
		//
		void parseHtml();

	private:
		//
		// parser context
		//
		xmlParserCtxtPtr													mParserContext;

		//
		// document content
		//
		DataBuffer															mDocumentContent;
	};
}
